<template>
  <div class="builder-container">
    <vol-box
      ref="add"
      :width="550"
      title="新建配置信息"
      :padding="0"
      v-model="addModel"
    >
      <div style="padding: 0">
        <el-alert type="warning" :closable="false">
          1、如果只是创建目录，父级id填0,其他随便填写;
          <br />
          2、如果是生成代码，父级id填写【代码生成配置】列表页面的id
        </el-alert>
      </div>
      <div class="addModel" style="padding-right: 30px">
        <vol-form ref="addForm" :formRules="addOptions" :formFields="layOutOptins.fields">
        </vol-form>
      </div>
      <template #footer>
        <div style="text-align: center;">
          <el-button type="primary" size="small" @click="add"
            ><i class="el-icon-plus"></i> 确 定</el-button
          >
        </div>
      </template>
    </vol-box>
    <div class="builder-left">
      <div class="module-name">代码生成配置</div>
      <div class="builder-tree">
        <el-scrollbar style="height: 100%; width: 200px">
          <!-- :onOpenChange="onOpenChange" -->
          <VolMenu :list="tree" :onSelect="onSelect"></VolMenu>
        </el-scrollbar>
      </div>
    </div>
    <div class="builder-content">
      <div style="height: 100%">
        <el-scrollbar style="height: 100%">
          <div class="coder-container">
            <div class="coder-item" style="padding-top: 7px">
              <VolHeader icon="ios-chatbubbles" text="代码生成器">
                <template #content>
                  <div style="color: red; font-size: 13px">
                    删除左侧配置菜单:删除行->保存->删除菜单
                  </div>
                </template>
                <div class="action">
                  <span @click="save"> <i class="el-icon-check"></i>保存 </span>
                  <span @click="addVisible()"> <i class="el-icon-plus"></i>新建 </span>
                  <span @click="ceateVuePage(0)">
                    <i class="el-icon-document"></i>生成Vue页面
                  </span>
                  <span @click="ceateVuePage(1)">
                    <i class="el-icon-document"></i>生成app页面
                  </span>
                  <span @click="ceateModel"> <i class="el-icon-tickets"></i>生成Model </span>
                  <span @click="createService"> <i class="el-icon-document"></i>生成业务类 </span>
                  <span @click="delTree"> <i class="el-icon-delete"></i>删除菜单 </span>
                </div>
              </VolHeader>
              <div class="config">
                <vol-form
                  :label-width="90"
                  ref="form"
                  :formRules="layOutOptins.options"
                  :formFields="layOutOptins.fields"
                ></vol-form>
              </div>
            </div>
            <el-alert type="warning" :closable="false">
              1、如果需要修改表结构，请在数据库修改，再点同步表结构->生成vue页面->生成model。
              2、修改编辑行后需要点击生成model、生成vue页面
            </el-alert>
            <div class="coder-item">
              <VolHeader icon="md-podium" style="border-bottom: 0" text="表结构">
                <template #content>
                  <div style="color: red; font-size: 13px">
                    数据库表结构发生变化时请点【同步表结构】
                  </div>
                </template>

                <div class="action">
                  <span @click="delRow" class="ivu-icon ivu-icon-md-close">删除行数据</span>
                  <span @click="syncTable" class="ivu-icon ivu-icon-md-sync">同步表结构</span>
                </div>
              </VolHeader>

              <div class="grid-container" style="padding-bottom: 20px">
                <vol-table
                  :sortable="true"
                  ref="table"
                  :paginationHide="true"
                  @onSortEnd="onSortEnd"
                  :tableData="data"
                  :height="tableHeight"
                  :columns="layOutOptins.columns"
                  :color="false"
                  :index="true"
                ></vol-table>
              </div>
            </div>
          </div>
        </el-scrollbar>
      </div>
    </div>
  </div>
</template>
<script>
import builderData from './builderData.jsx'
import VolHeader from '@/components/basic/VolHeader.vue'
import VolMenu from '@/components/basic/VolElementMenu.vue'
export default {
  components: {
    VolHeader: VolHeader,
    VolMenu
  },
  data() {
    return {
      more: {
        addChild: 'addChild',
        ceateController: 'ceateController',
        addRow: 'addRow',
        delRow: 'delRow',
        delTree: 'delTree'
      },
      addModel: false,
      helpModel: false,
      tableHeight: 500,
      addOptions: builderData.form.addOptions,
      layOutOptins: {
        fields: builderData.form.fields,
        options: builderData.form.options,
        columns: builderData.columns
      },
      tableInfo: null,
      data: [],
      tree: []
    }
  },
  watch: {
    'layOutOptins.fields.vuePath'(val) {
      localStorage.setItem('vuePath', val)
    },
    //deep: true
    //localStorage.setItem("vuePath", this.layOutOptins.fields.vuePath || "");
  },
  methods: {
    changeMore(funName) {
      this[funName]()
    },
    help() {
      window.open('http://v2.volcore.xyz/document/coder')
      // this.helpModel = true;
    },
    addVisible(pid) {
      this.addModel = true
      this.$refs.form.reset()
      this.data.splice(0)
      if (pid) {
        this.layOutOptins.fields.parentId = pid
      }
    },
    delTree() {
      let tableId = this.layOutOptins.fields.table_Id
      if (!tableId) return this.$message.error('请选择节点')
      let tigger = false
      this.$confirm('删除警告?', '确认要删除吗', {
        confirmButtonText: '确定',
        cancelButtonText: '取消',
        type: 'warning',
        center: true
      }).then(() => {
        if (tigger) return
        tigger = true
        this.http.post('/api/builder/delTree?table_Id=' + tableId, {}, true).then((x) => {
          if (!x.status) return this.$message.error(x.message)
          this.$message.error('删除成功,请刷新页面')
          // for (let index = 0; index < this.tree.length; index++) {
          //   if (this.tree[index].id == tableId) {
          //     this.tree.splice(index, 1);
          //   }
          // }
        })
      })
    },
    add() {
      this.$refs.form.validate(() => {

        if (!this.layOutOptins.fields.tableTrueName) {
          this.layOutOptins.fields.tableTrueName = this.layOutOptins.fields.tableName
        }

        let queryParam =
          'parentId=' +
          this.layOutOptins.fields.parentId +
          '&tableName=' +
          this.layOutOptins.fields.tableName +
          '&columnCNName=' +
          this.layOutOptins.fields.columnCNName +
          '&nameSpace=' +
          this.layOutOptins.fields.namespace +
          '&foldername=' +
          this.layOutOptins.fields.folderName +
          '&isTreeLoad=false'
        this.http.post('/api/builder/LoadTableInfo?' + queryParam, {}, true).then((x) => {
          if (!x.status) {
            this.$message.error(x.message)
            return
          }
          let hasTree = this.tree.some((t) => {
            return t.id == x.data.table_Id
          })
          if (!hasTree) {
            this.tree.push({
              id: x.data.table_Id,
              pId: x.data.parentId,
              parentId: x.data.parentId,
              name: x.data.columnCNName,
              orderNo: x.data.orderNo
            })
          }
          if (!x.data.tableTrueName) {
            x.data.tableTrueName = x.data.tableName
          }
          this.addModel = false
          this.tableInfo = x.data
          this.$refs.form.reset(x.data)
          this.data = x.data.tableColumns
        })
      })
    },
    addChild() {
      // this.$message.info("开发中");
      let id = this.layOutOptins.fields.table_Id
      if (!id) {
        return this.$message.error('请选中节点')
      }
      this.addVisible(id)
    },
    addRow() {
      this.data.push({})
    },
    delRow() {
      let tigger = false
      this.$confirm('删除警告?', '确认要删除选择的数据吗', {
        confirmButtonText: '确定',
        cancelButtonText: '取消',
        type: 'warning',
        center: true
      }).then(() => {
        if (tigger) return
        tigger = true
        this.$refs.table.delRow()
      })
    },
    validateTableInfo(callback) {
      this.$refs.form.validate(() => {
        if (!this.tableInfo) {
          this.$message.error('请先加载数据')
          return false
        }
        if (this.data && this.data.length > 0) {
          let keyInfo = this.data.find((x) => {
            return x.isKey
          })
          if (!keyInfo) {
            this.$message.error('请勾选设置主键')
            return false
          }
          if (keyInfo.isNull == 1) {
            this.$message.error('主键【可为空】必须设置为否')
            return false
          }
          if (
            keyInfo.columnType != 'int' &&
            keyInfo.columnType != 'bigint' &&
            !this.layOutOptins.fields.sortName
          ) {
            this.$message.error('主键非自增类型,请设置上面表单的【排序字段】')
            return false
          }
        }

        for (const key in this.tableInfo) {
          if (this.layOutOptins.fields.hasOwnProperty(key)) {
            let newVal = this.layOutOptins.fields[key]
            this.tableInfo[key] = newVal
          }
        }
        callback()
      })
    },
    ceateVuePage(isApp) {
      this.validateTableInfo(() => {
        let vuePath
        if (!isApp) {
          vuePath = localStorage.getItem('vuePath')
          if (!vuePath) {
            return this.$message.error('请先设置Vue项目对应Views的绝对路径,然后再保存!')
          }
        } else {
          vuePath = localStorage.getItem('appPath')
          if (!vuePath) {
            return this.$message.error('请先设置app路径,然后再保存!')
          }
        }

        let url = `/api/builder/createVuePage?vuePath=${vuePath}&vite=1&v3=1&app=${isApp || 0}`
        this.http.post(url, this.tableInfo, true).then((x) => {
          this.$Message.info(x)
        })
      })
    },
    createService() {
      this.validateTableInfo(() => {
        let queryParam =
          'tableName=' +
          this.layOutOptins.fields.tableName +
          '&nameSpace=' +
          this.layOutOptins.fields.namespace +
          '&foldername=' +
          this.layOutOptins.fields.folderName
        this.http
          .post('/api/builder/CreateServices?' + queryParam, this.tableInfo, true)
          .then((x) => {
            this.$Message.info(x)
          })
      })
    },
    ceateModel() {
      this.validateTableInfo(() => {
        this.http.post('/api/builder/CreateModel', this.tableInfo, true).then((x) => {
          this.$message.info(x)
        })
      })
    },
    syncTable() {
      if (!this.layOutOptins.fields.tableName) return this.$Message.error('请选模块')
      this.http
        .post('/api/builder/syncTable?tableName=' + this.layOutOptins.fields.tableName, {}, true)
        .then((x) => {
          if (!x.status) {
            return this.$Message.error(x.message)
          }
          this.$Message.info(x.message)
          this.loadTableInfo(this.layOutOptins.fields.table_Id)
        })
    },
    ceateApiController() {},
    ceateController() {},
    checkSortName() {},
    save() {
      localStorage.setItem('vuePath', this.layOutOptins.fields.vuePath || '')
      localStorage.setItem('appPath', this.layOutOptins.fields.appPath || '')

      if (
        this.tableInfo &&
        this.tableInfo.tableColumns &&
        this.tableInfo.tableColumns.length &&
        this.tableInfo.tableColumns.filter((x) => {
          return x.isKey == 1
        }).length > 1
      ) {
        return this.$Message.error('表结构只能勾选一个主键字段')
      }
      this.validateTableInfo(() => {
        this.http.post('/api/builder/Save', this.tableInfo, true).then((x) => {
          if (!x.status) {
            this.$Message.error(x.message)
            return
          }
          this.$Message.info(x.message)
          this.tree.forEach((x) => {
            if (x.id == this.layOutOptins.fields.table_Id) {
              x.name = this.layOutOptins.fields.columnCNName
              x.parentId = this.layOutOptins.fields.parentId
            }
          })
          this.tableInfo = x.data
          x.data.vuePath = this.layOutOptins.fields.vuePath
          x.data.appPath = this.layOutOptins.fields.appPath
          this.$refs.form.reset(x.data)
          //  this.layOutOptins.fields.vuePath = localStorage.getItem("vuePath");
          this.data = x.data.tableColumns
          //  this.$Message.info(x);
        })
      })
    },
    onSelect(node) {
      this.loadTableInfo(node)
    },
    onOpenChange(node) {
      if (node.length == 0) return
      this.loadTableInfo(node.length == 1 ? node[0] : node[node.length - 1])
    },
    loadTableInfo(id) {
      // localStorage.setItem("vuePath", this.layOutOptins.fields.vuePath || "");
      this.http
        .post('/api/builder/LoadTableInfo?table_Id=' + id + '&isTreeLoad=true', {}, true)
        .then((x) => {
          if (!x.data.tableTrueName) {
            x.data.tableTrueName = x.data.tableName
          }
          const _fields = ['sortable', 'isNull', 'isReadDataset', 'isColumnData', 'isDisplay']
          x.data.tableColumns.forEach((item) => {
            for (let index = 0; index < _fields.length; index++) {
              item[_fields[index]] = item[_fields[index]] || 0
            }
          })
          this.tableInfo = x.data

          this.$refs.form.reset(x.data)
          this.data = x.data.tableColumns
        })
    },
    getVuePath(key) {
      let vuePath = localStorage.getItem(key)
      if (!vuePath || vuePath == 'null' || vuePath == 'undefined') {
        vuePath = ''
      }
      return vuePath
    },
    onSortEnd(rows) {
      let orderNo = 10000
      rows.forEach((x) => {
        orderNo = orderNo - 50
        x.orderNo = orderNo
      })
    }
  },
  mounted() {},
  created() {
    let clientHeight = document.documentElement.clientHeight - 170
    this.tableHeight = clientHeight < 400 ? 400 : clientHeight
    this.http.post('/api/Sys_Dictionary/GetBuilderDictionary', {}, true).then((dic) => {
      let column = this.layOutOptins.columns.find((x) => {
        return x.field == 'dropNo'
      })
      if (!column) return

      let data = [{ key: '', value: '' }]
      for (let index = 0; index < dic.length; index++) {
        data.push({ key: dic[index], value: dic[index] })
      }

      column.bind.data = data
    })

    builderData.form.fields.vuePath = this.getVuePath('vuePath')
    builderData.form.fields.appPath = this.getVuePath('appPath')
    this.http.post('/api/builder/GetTableTree', {}, false).then((x) => {
      let list = JSON.parse(x.list)
      list.forEach((c) => {
        if (
          c.parentId &&
          !list.some((a) => {
            return a.id == c.parentId
          })
        ) {
          c.parentId = 0
          c.pId = 0
        }
      })
      this.tree = list
      if (!x.nameSpace) {
        return this.$message.error(
          '未获取后台项目类库所在命名空间,请确认目录或调试Sys_TableInfoService类GetTableTree方法'
        )
      }
      let nameSpace = JSON.parse(x.nameSpace)
      let nameSpaceArr = []
      for (let index = 0; index < nameSpace.length; index++) {
        nameSpaceArr.push({
          key: nameSpace[index],
          value: nameSpace[index]
        })
      }

      //初始化项目命令空间
      this.layOutOptins.options.forEach((option) => {
        option.forEach((item) => {
          if (item.field == 'namespace') {
            item.data.push(...nameSpaceArr)
          }
        })
      })
      this.addOptions.forEach((option) => {
        option.forEach((item) => {
          if (item.field == 'namespace') {
            item.data.push(...nameSpaceArr)
          }
        })
      })
    })
  }
}
</script>
<style scoped>
.builder-tree {
  position: absolute;
  top: 41px;
  bottom: 0;
}

.builder-container {
  widows: 100%;
  /* padding: 20px; */
  position: absolute;
  top: 0px;
  left: 0;
  right: 0;
  display: inline-block;
  bottom: 0;
}


.builder-left {
  position: relative;
  width: 201px;
  height: 100%;
  border-right: 2px solid #dcd6d6;
}

.builder-content {
  position: absolute;
  top: 0px;
  left: 200px;
  display: inline-block;
  bottom: 0;
  right: 0px;
}

.builder-content .ivu-alert {
  position: relative;
  display: flex;
  padding: 12px 18px 12px 38px;
}

.builder-content .ivu-alert-icon {
  top: 10px;
}

.builder-content .action {
  text-align: right;
  line-height: 33px;
  padding-right: 26px;
}

.builder-content .action i {
  top: 0px;
  position: relative;
}

.builder-content .action > span {
  padding: 0px 6px;
  font-size: 12px;
  letter-spacing: 1px;
  color: #5a5f5e;
}

.builder-content .action > span:hover {
  cursor: pointer;
  color: black;
}

.builder-content .config {
  /* border: 1px solid #e9e8e8; */
  padding: 15px 15px 0px 15px;
  border-radius: 3px;
  background: #ffffff;
  margin-bottom: 10px;
}

.coder-container {
  background: #eee;
}

.coder-container .coder-item {
  background: white;
  padding: 0px 15px;
}

.module-name {
  color: #2d8cf0;
  font-size: 13px;
  line-height: 39px;
  padding-left: 15px;
  border: 1px solid #abdcff;
  background-color: #f0faff;
}


.help {
  margin-left: 15px;
  top: 2px;
  position: relative;
  border-bottom: 1px solid;
}

.help:hover {
  color: #f56c6c;
  cursor: pointer;
}

.more {
  text-align: left;
  position: relative;
  top: 2px;
}

.addModel {
  padding: 10px;
}
</style>
